import React, { useState, useEffect, useRef, useCallback } from 'react'
const boxStyle = {
  margin: '10px',
  border: '1px solid #ccc',
  borderRadius: '10px',
  padding: '10px',
}
const flexBox = {
  display: 'flex',
  justifyContent: 'space-around',
  flexWrap: 'wrap',
}

export function FormUseCallback() {
  const [text, updateText] = useState('0')
  const textRef = useRef()

  useEffect(() => {
    textRef.current = text // 把它写入 ref
    console.log("render...useEffect...change...textRef.current...", text, textRef.current)
  })
  
  // ref属性只会在初次生成实例时挂载,后面不更新, 除非手动重新卸载挂载组件
  // 故绑定后监听  refs对象不会重发触发
  useEffect(()=>{
    console.log('textRef...useEffect...', textRef)
  },[textRef])

  // textRef.current修改则会监听到
  useEffect(()=>{
    console.log('textRef.current...useEffect', textRef.current)
  },[textRef.current])


  // 当useCallback和useEffect第二个参数为空时, 其中使用的useState值为初始值
  const handleSubmit0 = useCallback(() => {
    console.log('使用的是第一传入的useState的值...',text)
  }, [])

  // 使用这个特性 textRef不频繁更新, textRef.current更新来解决上述问题 曲线实现    
  const handleSubmit = useCallback(() => {
    const currentText = textRef.current // 从 ref 读取它
    alert(currentText)
  }, [textRef]) // 不要像 [text] 那样重新创建 handleSubmit

  return (
    <div style={boxStyle}>
      <p>使用useEffect和useCallback监听Ref及Ref.value</p>
      {/* 由于textRef会在每次渲染结束才会绑定 */}
      <p>这是ref的值:{textRef.current}</p>
      <input value={text} onChange={(e) => updateText(e.target.value)} />
      <button onClick={handleSubmit0}>使用 handleSubmit0</button>
      <ExpensiveTree onSubmit={handleSubmit} />
    </div>
  )
}

function ExpensiveTree(props) {
  return (
    <>
      <input type="submit" onSubmit={props.onSubmit} value="提交" />
    </>
  )
}
